import json

from django.db import models
from django.core.validators import RegexValidator

from ygmsp_dj.settings import SECRET_KEY

from utils.vault import encrypt
from utils.strings import underline_to_camelcase

import logging
logger = logging.getLogger(__name__)
logger.success = lambda msg, *args, **kwargs: logger.log(25, msg, *args, **kwargs)

# Azure ID的正则表达式校验
validate_azure_id = RegexValidator(r'^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$')

# Create your models here.
class Auth(models.Model):
    name = models.CharField(max_length=32)
    display_name = models.CharField(max_length=128, blank=True)
    AZURE_CLOUDS = [
        ('AZURE_PUBLIC_CLOUD', 'AzureCloud'),
        ('AZURE_CHINA_CLOUD', 'AzureChinaCloud'),
        ('AZURE_US_GOV_CLOUD', 'AzureUSGovernment'),
        ('AZURE_GERMAN_CLOUD', 'AzureGermanCloud')
    ]
    cloud = models.CharField(max_length=32, choices=AZURE_CLOUDS, default='AZURE_CHINA_CLOUD')
    client_id = models.CharField(max_length=128, validators=[validate_azure_id])
    tenant_id = models.CharField(max_length=128, validators=[validate_azure_id])
    client_secret = models.TextField(max_length=512)

    def __str__(self):
        return self.name

    def save(self, *args, **kwargs):
        """重写save方法,在save之前对client_secret加密"""
        self.client_secret = encrypt(self.client_secret, SECRET_KEY)
        super().save(*args, **kwargs)


class Subscriptions(models.Model):
    id = models.CharField(max_length=128, validators=[validate_azure_id], primary_key=True, verbose_name='subscription_id')
    name = models.CharField(max_length=128, verbose_name='display_name')
    old_name = models.CharField(max_length=128, default='', blank=True)
    ctime = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    uptime = models.DateTimeField(auto_now=True, verbose_name="更新时间")
    auth = models.ForeignKey(Auth, on_delete=models.CASCADE)

    def __str__(self):
        return self.name


class Resources(models.Model):
    id = models.CharField(max_length=512, primary_key=True, verbose_name='sresource_id')
    name = models.CharField(max_length=128, verbose_name="名称")
    type = models.CharField(max_length=128, verbose_name="类型")
    tenant_id = models.CharField(max_length=128, validators=[validate_azure_id])
    kind = models.CharField(max_length=128)
    location = models.CharField(max_length=128, verbose_name="位置")
    resource_group = models.CharField(max_length=128, verbose_name="资源组")
    managed_by = models.CharField(max_length=512)
    sku = models.JSONField(null=True)
    plan = models.JSONField(null=True)
    properties = models.JSONField(null=True)
    tags = models.JSONField(null=True)
    identity = models.JSONField(null=True)
    
    ctime = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    uptime = models.DateTimeField(auto_now=True, verbose_name="更新时间")
    del_time = models.DateTimeField(null=True, default=None, verbose_name="删除时间")

    subscription = models.ForeignKey(Subscriptions, on_delete=models.CASCADE)

    def __str__(self):
        return self.name

    def save_by_resource_graph(self, data):
        """当前记录self和data的字典对比, 如果值改变了, 才调用save方法保存"""
        check_list = ['name', 'type', 'tenant_id', 'kind', 'location', 'resource_group', 'managed_by']
        check_list_json = ['sku', 'plan', 'properties', 'tags', 'identity']

        changed_list = []
        for i in check_list:
            key = underline_to_camelcase(i)
            old = getattr(self, i) 
            new = data[key]
            if old != new:
                changed_list.append((i, new))
        for i in check_list_json:
            # json需要先转为字典再比较，每次请求返回的key的顺序可能是不同的
            key = underline_to_camelcase(i)
            old = getattr(self, i)
            old_obj = json.loads(old)
            new_obj = data[key]
            if old_obj != new_obj:
                new = json.dumps(new_obj)
                changed_list.append((i, new))
        
        if changed_list:
            # properties 更新太普遍了，并且不能确认是否有变了配置
            if len(changed_list) == 1 and changed_list[0][0] == 'properties':
                logger.debug(f'资源properties字段更新: {self.id}')
            else:
                logger.info('资源字段有更新: {} 字段列表=[{}]'.format(self.id, ' '.join([ i[0] for i in changed_list ])))
            for i, new in changed_list:
                setattr(self, i, new)
            self.save()
            return [ i[0] for i in changed_list ]

    def save(self, *args, **kwargs):
        """重写save方法
        id内容要全部转小写
        """
        self.id = self.id.lower()
        super().save(*args, **kwargs)
                

